package com.naiterui.ehp.bs.b2c.order.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.naiterui.ehp.bp.bo.b2c.order.ReturnOrderBO;
import com.naiterui.ehp.bp.bo.b2c.order.ReturnOrderItemBO;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.payment.OrderUtils;
import com.naiterui.ehp.bs.b2c.order.entity.ReturnOrder;
import com.naiterui.ehp.bs.b2c.order.exception.OrderExceptionCodes;
import com.naiterui.ehp.bs.b2c.order.repository.IReturnOrderRepository;
import com.naiterui.ehp.bs.b2c.order.service.IReturnOrderItemService;
import com.naiterui.ehp.bs.b2c.order.service.IReturnOrderOperateLogService;
import com.naiterui.ehp.bs.b2c.order.service.IReturnOrderService;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description 退、换、补寄订单业务逻辑实现类
 * @Author gongbaoqiang
 * @Date 2019/9/29 2:48 PM
 */
@Slf4j
@Service
public class ReturnOrderServiceImpl implements IReturnOrderService {

    @Autowired
    private IReturnOrderRepository orderRepository;
    @Autowired
    private IReturnOrderItemService itemService;
    @Autowired
    private IReturnOrderOperateLogService operateLogService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(ReturnOrderBO bo, String operator) throws BusinessException {
        ReturnOrder returnOrder = null;
        //step1-1: 新增订单
        if (bo.getId() == null) {
            log.info("新增退货订单");
            returnOrder = this.addOrder(bo, operator);
            //新增明细

            //增加新增日志
            this.operateLogService.add(returnOrder.getBusinessNo(), operator);
        } else { //step1-2: 修改订单
            log.info("修改退货订单");
            returnOrder = this.updateOrder(bo, operator);
            //删除明细，然后统一添加
            this.itemService.delByBusinessNo(returnOrder.getBusinessNo());
            this.operateLogService.update(returnOrder.getBusinessNo(), operator);
        }

        //合并退货列表和换补货列表
        List<ReturnOrderItemBO> itemlist = new ArrayList<>();

        //todo: 1. 根据订单号和skuId查询订单明细，获取药品信息 2. 设置明细类型为退货，增加退换货业务单号和原订单号
        if (CollectionUtil.isNotEmpty(bo.getReturnProducts())) {
            CollectionUtil.addAll(itemlist, bo.getReturnProducts());
        }

        //todo: 1. 根据skuId查询商品信息 2. 设置明细类型为换货/补寄，增加退换货业务单号和原订单号
        if (CollectionUtil.isNotEmpty(bo.getExchanges())) {
            CollectionUtil.addAll(itemlist, bo.getExchanges());
        }
        this.itemService.addList(itemlist, returnOrder.getBusinessNo(), returnOrder.getOrderSn(), operator);
    }

    @Override
    public void submit(List<Long> ids, String operator) throws BusinessException {
        List<String> businessNos = this.updateStatus(ids, ReturnOrder.STATUS_TO_AUDIT, operator,
                                                     OrderExceptionCodes.RETURN_ORDER_NOT_SUBMIT, ReturnOrder.STATUS_TO_SUBMIT);
        this.operateLogService.submit(businessNos, operator);
    }

    @Override
    public void audit(List<Long> ids, String operator) throws BusinessException {
        List<String> businessNos = this.updateStatus(ids, ReturnOrder.STATUS_TO_SEND,
                                                     operator, OrderExceptionCodes.RETURN_ORDER_NOT_AUDIT, ReturnOrder.STATUS_TO_AUDIT);
        this.operateLogService.audit(businessNos, operator);

    }

    @Override
    public void reset(List<Long> ids, String operator) throws BusinessException {
        List<String> businessNos = this.updateStatus(ids, ReturnOrder.STATUS_TO_SUBMIT, operator,
                                                     OrderExceptionCodes.RETURN_ORDER_NOT_RESET, ReturnOrder.STATUS_TO_AUDIT,
                                                     ReturnOrder.STATUS_TO_SEND);
        this.operateLogService.reset(businessNos, operator);
    }


    @Override
    public void invalid(List<Long> ids, String operator) throws BusinessException {
        List<String> businessNos = this.updateStatus(ids, ReturnOrder.STATUS_INVALID, operator,
                                                     OrderExceptionCodes.RETURN_ORDER_NOT_INVALID, ReturnOrder.STATUS_TO_SUBMIT);
        this.operateLogService.invalid(businessNos, operator);
    }

    @Override
    public void confirm(List<Long> ids, String operator) throws BusinessException {
        List<String> businessNos = this.updateStatus(ids, ReturnOrder.STATUS_COMPLETE, operator,
                                                     OrderExceptionCodes.RETURN_ORDER_NOT_CONFIRM, ReturnOrder.STATUS_TO_SEND);
        this.operateLogService.confirm(businessNos, operator);
    }

    /**
     * 添加退换货订单
     *
     * @param bo
     * @param operator
     *
     * @throws BusinessException
     */
    private ReturnOrder addOrder(ReturnOrderBO bo, String operator) throws BusinessException {
        ReturnOrder returnOrder = new ReturnOrder();
        BeanUtils.copyProperties(bo, returnOrder);
        //生成业务单号
        String bsn = "";
        switch (bo.getType()) {
            case ReturnOrder.TYPE_RETURN:
                bsn = OrderUtils.getBusinessSn("rt");
                break;
            case ReturnOrder.TYPE_EXCHANGE:
                bsn = OrderUtils.getBusinessSn("ex");
                break;
            case ReturnOrder.TYPE_SUPPLEMENTARY:
                bsn = OrderUtils.getBusinessSn("ad");
                break;
            default:
                bsn = OrderUtils.getBusinessSn("rt");
        }
        returnOrder.setBusinessNo(bsn);
        returnOrder.setCreatedAt(new Date());
        returnOrder.setCreatedBy(operator);
        returnOrder.setStatus((bo.getSubmitFlag() != null && bo.getSubmitFlag() == 1) ? ReturnOrder.STATUS_TO_AUDIT : ReturnOrder.STATUS_TO_SUBMIT);
        log.info("保存退货订单详细信息：entity={}", returnOrder.toString());
        //保存退货订单主信息
        this.orderRepository.save(returnOrder);
        return returnOrder;
    }

    /**
     * <pre>
     *     修改订单信息
     * </pre>
     *
     * @param bo
     * @param operator
     *
     * @throws BusinessException
     */
    private ReturnOrder updateOrder(ReturnOrderBO bo, String operator) throws BusinessException {
        ReturnOrder returnOrder = this.orderRepository.get(bo.getId());
        if (returnOrder == null) {
            throw new BusinessException(OrderExceptionCodes.RETURN_ORDER_NOT_EXISTS);
        }
        //校验订单状态：非待提交状态不允许修改
        if (ReturnOrder.STATUS_TO_SUBMIT != returnOrder.getStatus()) {
            log.error("非待提交状态不允许修改：businessNo={}, status={}", bo.getBusinessNo(), returnOrder.getStatus());
            throw new BusinessException(OrderExceptionCodes.RETURN_ORDER_NOT_MODIFY);
        }
        returnOrder.setChangedAt(new Date());
        returnOrder.setChangedBy(operator);
        BeanUtils.copyProperties(bo, returnOrder, "businessNo");
        returnOrder.setStatus((bo.getSubmitFlag() != null && bo.getSubmitFlag() == 1) ? ReturnOrder.STATUS_TO_AUDIT : ReturnOrder.STATUS_TO_SUBMIT);
        log.info("修改退货订单详细信息：entity={}", returnOrder.toString());
        //step2: 保存退货订单主信息
        this.orderRepository.save(returnOrder);
        return returnOrder;
    }

    /**
     * 更新订单状态，并返回批量操作业务单号
     *
     * @param ids           批量操作订单id
     * @param status        更新后状态
     * @param operator      操作人
     * @param exceptionCode 异常码
     * @param operator      期望的原数据状态
     *
     * @return
     *
     * @throws BusinessException
     */
    private List<String> updateStatus(List<Long> ids, int status, String operator,
                                      int exceptionCode, int... exceptStatus) throws BusinessException {
        Iterable<ReturnOrder> allList = this.orderRepository.findAllById(ids);
        Iterator<ReturnOrder> iterator = allList.iterator();
        List<String> businessNos = new ArrayList<>();

        while (iterator.hasNext()) {
            ReturnOrder s = iterator.next();
            boolean validFlag = false;
            if (exceptStatus.length > 0) {
                for (int i = 0; i < exceptStatus.length; i++) {
                    if (s.getStatus() == exceptStatus[i]) {
                        validFlag = true;
                        break;
                    }
                }
                //校验订单状态：只有符合期望状态的订单才能进行相应的状态更新操作
                if (!validFlag) {
                    log.error("退换货订单状态更新失败：ids={}, status={} ", StringUtils.join(ids, ","), status);
                    throw new BusinessException(exceptionCode);
                }
            }

            s.setStatus(status);
            s.setChangedBy(operator);
            s.setChangedAt(new Date());
            businessNos.add(s.getBusinessNo());
        }

        this.orderRepository.save(allList);
        log.info("更新订单状态成功：ids={}, status={} ", StringUtils.join(ids, ","), status);
        return businessNos;
    }

}
